﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Onetube.Entities.ActivityQuery;
using Onetube.Providers.Interfaces;
using System.Linq;
using Onetube.Models.SearchVideo;
using Onetube.Entities.RecentUploadedVideosQueryResult;
using Newtonsoft.Json.Linq;
using Onetube.Models;
using System.Text.RegularExpressions;
using System.Xml.Linq;

namespace Onetube.Providers
{
    public class ActivityProvider : IActivityProvider
    {
        private YoutubeVideoProvider videoProvider;
        private YoutubeChannelProvider channelProvider;

        public async Task<Models.SearchVideo.SearchVideoResult> GetMyActivitiesAsync(string token, string regionCode, string maxResults, System.Threading.CancellationTokenSource cancelTask)
        {
            StringBuilder petitionUri = new StringBuilder("https://www.googleapis.com/youtube/v3/activities?");

            petitionUri.AppendFormat("part={0}", "snippet%2CcontentDetails");
            petitionUri.AppendFormat("&home={0}", "true");
            petitionUri.AppendFormat("&maxResults={0}", maxResults);
            petitionUri.AppendFormat("&regionCode={0}", regionCode);
            petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);
          
            var taskCompletitionSource = new TaskCompletionSource<Entities.ActivityQuery.ActivityQueryResult>();
            HttpWebRequest request = HttpWebRequest.CreateHttp(petitionUri.ToString());
            request.Headers["Authorization"] = "Bearer  " + token;

            var videoResult = new Models.SearchVideo.SearchVideoResult();
            var result = await ResolveRequest(request, taskCompletitionSource, cancelTask).ConfigureAwait(false);
            if (result != null)
            {
                videoResult.etag = result.Etag;
                videoResult.kind = result.Kind;
                videoResult.nextPageToken = result.NextPageToken;
                videoResult.pageInfo = new Models.SearchVideo.PageInfo { resultsPerPage = result.PageInfo.ResultsPerPage, totalResults = result.PageInfo.TotalResults };
                
                videoResult.items = new List<Models.SearchVideo.Item>();
                if (result.Items != null)
                {
                    if (result.Items.Any())
                    {
                        videoProvider = new YoutubeVideoProvider();
                        channelProvider = new YoutubeChannelProvider();
                        string videoIds = string.Empty;
                        string channelIds = string.Empty;
                        int count = 0;
                        for (int i = 0; i <= result.Items.Count - 1; i++)
                        {
                            count++;
                            var item = result.Items.ElementAt(i);

                            if (item.ContentDetails.Recommendation != null)
                            {
                                if (item.ContentDetails.Recommendation.ResourceId.VideoId != null)
                                {
                                    if (count >= result.Items.Count)
                                    {
                                        videoIds += item.ContentDetails.Recommendation.ResourceId.VideoId;
                                        channelIds += item.Snippet.ChannelId;
                                    }
                                    else
                                    {
                                        videoIds += item.ContentDetails.Recommendation.ResourceId.VideoId + ",";
                                        channelIds += item.Snippet.ChannelId + ",";
                                    }
                                }
                            }
                        }

                        var videoDataList = await videoProvider.GeVideoInfoAsync(videoIds, "MX", cancelTask);
                        var channelDataList = await channelProvider.SearchChannelByIdAsync(channelIds, cancelTask);
                        if (videoDataList != null)
                        {
                            foreach (var videoItem in result.Items.Where(x => x.ContentDetails.Recommendation != null))
                            {
                                var dataItem = new Onetube.Models.SearchVideo.Item();
                              
                                dataItem.etag = videoResult.etag;
                                dataItem.id = new Onetube.Models.SearchVideo.Id { kind = videoItem.Kind, videoId = videoItem.ContentDetails.Recommendation.ResourceId.VideoId };
                                dataItem.kind = videoItem.Kind;
                                var snippet = new Onetube.Models.SearchVideo.Snippet();
                                snippet.channelId = videoItem.Snippet.ChannelId;
                                snippet.channelTitle = videoItem.Snippet.ChannelTitle;
                                snippet.description = videoItem.Snippet.Description;
                                snippet.liveBroadcastContent = string.Empty;
                                snippet.publishedAt = videoItem.Snippet.PublishedAt;
                                snippet.title = videoItem.Snippet.Title;
                                snippet.thumbnails = new Onetube.Models.SearchVideo.Thumbnails 
                                {
                                    @default = new Onetube.Models.SearchVideo.Default { url = videoItem.Snippet.Thumbnails.Default.Url },
                                    high = new Onetube.Models.SearchVideo.High { url = videoItem.Snippet.Thumbnails.High.Url },
                                    medium = new Onetube.Models.SearchVideo.Medium { url = videoItem.Snippet.Thumbnails.Medium.Url }
                                };
                                var contentDetails = new Onetube.Models.SearchVideo.ContentDetails();
                                var correspondVideo = videoDataList.Items.FirstOrDefault(x => x.Id.Equals(videoItem.ContentDetails.Recommendation.ResourceId.VideoId));
                                if (correspondVideo != null)
                                {
                                    contentDetails.caption = correspondVideo.ContentDetails.Caption;
                                    contentDetails.definition = correspondVideo.ContentDetails.Definition;
                                    contentDetails.dimension = correspondVideo.ContentDetails.Dimension;
                                    contentDetails.duration = correspondVideo.ContentDetails.Duration;
                                    contentDetails.licensedContent = correspondVideo.ContentDetails.LicensedContent;
                                }

                                snippet.contentDetails = contentDetails;

                                var statistics = new Onetube.Models.SearchVideo.Statistics();
                                statistics.commentCount = correspondVideo.Statistics.CommentCount;
                                statistics.dislikeCount = correspondVideo.Statistics.DislikeCount;
                                statistics.favoriteCount = correspondVideo.Statistics.FavoriteCount;
                                statistics.likeCount = correspondVideo.Statistics.LikeCount;
                                statistics.viewCount = correspondVideo.Statistics.ViewCount;

                                snippet.statistics = statistics;
                                dataItem.snippet = snippet;
                                if (channelDataList != null)
                                {
                                    if (channelDataList.Items.Any())
                                    {
                                        var correspondChannel = channelDataList.Items.FirstOrDefault(x => x.Id.Equals(videoItem.Snippet.ChannelId));
                                        if (correspondChannel != null)
                                        {
                                            dataItem.snippet.channelDetails = new ChannelSnippet();
                                            dataItem.snippet.channelDetails.Description = correspondChannel.Snippet.Description;
                                            dataItem.snippet.channelDetails.PublishedAt = correspondChannel.Snippet.PublishedAt;
                                            dataItem.snippet.channelDetails.Thumbnails = new Models.SearchVideo.Thumbnails
                                            {
                                                @default = new Models.SearchVideo.Default
                                                {
                                                    url = correspondChannel.Snippet.Thumbnails.Default.Url
                                                },
                                                high = new Models.SearchVideo.High
                                                {
                                                    url = correspondChannel.Snippet.Thumbnails.High.Url
                                                },
                                                medium = new Models.SearchVideo.Medium
                                                {
                                                    url = correspondChannel.Snippet.Thumbnails.Medium.Url
                                                }
                                            };
                                            dataItem.snippet.channelDetails.Title = correspondChannel.Snippet.Title;
                                        }
                                    }
                                }
                                videoResult.items.Add(dataItem);
                            }
                            videoDataList = null;
                            channelDataList = null;
                            videoIds = null;
                            channelIds = null;
                        }
                    }
                }
                result = null;
            }

            return videoResult;
        }

        public async Task<Models.SearchVideo.SearchVideoResult> GetMyActivitiesNextPageAsync(string token, string nextPageToken, string regionCode, string maxResults, System.Threading.CancellationTokenSource cancelTask)
        {
            StringBuilder petitionUri = new StringBuilder("https://www.googleapis.com/youtube/v3/activities?");

            petitionUri.AppendFormat("part={0}", "snippet%2CcontentDetails");
            petitionUri.AppendFormat("&home={0}", "true");
            petitionUri.AppendFormat("&maxResults={0}", maxResults);
            petitionUri.AppendFormat("&regionCode={0}", regionCode);
            petitionUri.AppendFormat("&pageToken={0}", nextPageToken);
            petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);
          
            var taskCompletitionSource = new TaskCompletionSource<Entities.ActivityQuery.ActivityQueryResult>();
            HttpWebRequest request = HttpWebRequest.CreateHttp(petitionUri.ToString());
            request.Headers["Authorization"] = "Bearer  " + token;
            var videoResult = new Models.SearchVideo.SearchVideoResult();
            var result = await ResolveRequest(request, taskCompletitionSource, cancelTask);
            if (result != null)
            {
                videoResult.etag = result.Etag;
                videoResult.kind = result.Kind;
                videoResult.nextPageToken = result.NextPageToken;
                videoResult.pageInfo = new Models.SearchVideo.PageInfo { resultsPerPage = result.PageInfo.ResultsPerPage, totalResults = result.PageInfo.TotalResults };
                
                videoResult.items = new List<Models.SearchVideo.Item>();
                if (result.Items != null)
                {
                    if (result.Items.Any())
                    {
                        videoProvider = new YoutubeVideoProvider();
                        channelProvider = new YoutubeChannelProvider();
                        string videoIds = string.Empty;
                        string channelIds = string.Empty;
                        int count = 0;
                        for (int i = 0; i <= result.Items.Count - 1; i++)
                        {
                            count++;
                            var item = result.Items.ElementAt(i);

                            if (item.ContentDetails.Recommendation != null)
                            {
                                if (item.ContentDetails.Recommendation.ResourceId.VideoId != null)
                                {
                                    if (count >= result.Items.Count)
                                    {
                                        videoIds += item.ContentDetails.Recommendation.ResourceId.VideoId;
                                        channelIds += item.Snippet.ChannelId;
                                    }
                                    else
                                    {
                                        videoIds += item.ContentDetails.Recommendation.ResourceId.VideoId + ",";
                                        channelIds += item.Snippet.ChannelId + ",";
                                    }
                                }
                            }
                        }

                        var videoDataList = await videoProvider.GeVideoInfoAsync(videoIds, "MX", cancelTask);
                        var channelDataList = await channelProvider.SearchChannelByIdAsync(channelIds, cancelTask);
                        if (videoDataList != null)
                        {
                            foreach (var videoItem in result.Items.Where(x => x.ContentDetails.Recommendation != null))
                            {
                                var dataItem = new Onetube.Models.SearchVideo.Item();
                              
                                dataItem.etag = videoResult.etag;
                                dataItem.id = new Onetube.Models.SearchVideo.Id { kind = videoItem.Kind, videoId = videoItem.ContentDetails.Recommendation.ResourceId.VideoId };
                                dataItem.kind = videoItem.Kind;
                                var snippet = new Onetube.Models.SearchVideo.Snippet();
                                snippet.channelId = videoItem.Snippet.ChannelId;
                                snippet.channelTitle = videoItem.Snippet.ChannelTitle;
                                snippet.description = videoItem.Snippet.Description;
                                snippet.liveBroadcastContent = string.Empty;
                                snippet.publishedAt = videoItem.Snippet.PublishedAt;
                                snippet.title = videoItem.Snippet.Title;
                                snippet.thumbnails = new Onetube.Models.SearchVideo.Thumbnails 
                                {
                                    @default = new Onetube.Models.SearchVideo.Default { url = videoItem.Snippet.Thumbnails.Default.Url },
                                    high = new Onetube.Models.SearchVideo.High { url = videoItem.Snippet.Thumbnails.High.Url },
                                    medium = new Onetube.Models.SearchVideo.Medium { url = videoItem.Snippet.Thumbnails.Medium.Url }
                                };
                                var contentDetails = new Onetube.Models.SearchVideo.ContentDetails();
                                var correspondVideo = videoDataList.Items.FirstOrDefault(x => x.Id.Equals(videoItem.ContentDetails.Recommendation.ResourceId.VideoId));
                                if (correspondVideo != null)
                                {
                                    contentDetails.caption = correspondVideo.ContentDetails.Caption;
                                    contentDetails.definition = correspondVideo.ContentDetails.Definition;
                                    contentDetails.dimension = correspondVideo.ContentDetails.Dimension;
                                    contentDetails.duration = correspondVideo.ContentDetails.Duration;
                                    contentDetails.licensedContent = correspondVideo.ContentDetails.LicensedContent;
                                }

                                snippet.contentDetails = contentDetails;

                                var statistics = new Onetube.Models.SearchVideo.Statistics();
                                statistics.commentCount = correspondVideo.Statistics.CommentCount;
                                statistics.dislikeCount = correspondVideo.Statistics.DislikeCount;
                                statistics.favoriteCount = correspondVideo.Statistics.FavoriteCount;
                                statistics.likeCount = correspondVideo.Statistics.LikeCount;
                                statistics.viewCount = correspondVideo.Statistics.ViewCount;

                                snippet.statistics = statistics;
                                dataItem.snippet = snippet;
                                if (channelDataList != null)
                                {
                                    if (channelDataList.Items.Any())
                                    {
                                        var correspondChannel = channelDataList.Items.FirstOrDefault(x => x.Id.Equals(videoItem.Snippet.ChannelId));
                                        if (correspondChannel != null)
                                        {
                                            dataItem.snippet.channelDetails = new ChannelSnippet();
                                            dataItem.snippet.channelDetails.Description = correspondChannel.Snippet.Description;
                                            dataItem.snippet.channelDetails.PublishedAt = correspondChannel.Snippet.PublishedAt;
                                            dataItem.snippet.channelDetails.Thumbnails = new Models.SearchVideo.Thumbnails
                                            {
                                                @default = new Models.SearchVideo.Default
                                                {
                                                    url = correspondChannel.Snippet.Thumbnails.Default.Url
                                                },
                                                high = new Models.SearchVideo.High
                                                {
                                                    url = correspondChannel.Snippet.Thumbnails.High.Url
                                                },
                                                medium = new Models.SearchVideo.Medium
                                                {
                                                    url = correspondChannel.Snippet.Thumbnails.Medium.Url
                                                }
                                            };
                                            dataItem.snippet.channelDetails.Title = correspondChannel.Snippet.Title;
                                        }
                                    }
                                }
                                videoResult.items.Add(dataItem);
                            }
                            videoDataList = null;
                            channelDataList = null;
                            videoIds = null;
                            channelIds = null;
                        }
                    }
                }
                result = null;
            }

            return videoResult;
        }

        private async Task<ActivityQueryResult> ResolveRequest(HttpWebRequest request, TaskCompletionSource<ActivityQueryResult> taskCompletitionSource, CancellationTokenSource cancelTask)
        {
            if (cancelTask == null)
            {
                cancelTask = new CancellationTokenSource();
            }
           
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("Authorization", request.Headers["Authorization"]);
                HttpResponseMessage response = await client.GetAsync(request.RequestUri.ToString(), cancelTask.Token).ConfigureAwait(false);
                
                string resultJson;
                using (StreamReader reader = new StreamReader(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), Encoding.UTF8))
                {
                    try
                    {
                        resultJson = await reader.ReadToEndAsync().ConfigureAwait(false);

                        if (!string.IsNullOrEmpty(resultJson))
                        {
                            var entries = JsonConvert.DeserializeObject<ActivityQueryResult>(resultJson);

                            taskCompletitionSource.SetResult(entries);
                            resultJson = null;
                            entries = null;
                            response.Dispose();
                        }
                        else
                        {
                            taskCompletitionSource.SetResult(null);
                        }
                    }
                    catch (Exception ex)
                    {
                        taskCompletitionSource.SetException(ex);
                    }
                }
                  response.Dispose();
            }

            return await taskCompletitionSource.Task;
        }

        private async Task<RecentUploadedVideosQueryResult> ResolveRequest(StringBuilder petitionUri, TaskCompletionSource<RecentUploadedVideosQueryResult> taskCompletitionSource, CancellationTokenSource cancelTask)
        {
            if (cancelTask == null)
            {
                cancelTask = new CancellationTokenSource();
            }
           
            using (HttpClient client = new HttpClient())
            {
                // client.DefaultRequestHeaders.Add("Authorization", request.Headers["Authorization"]);
                HttpResponseMessage response = await client.GetAsync(petitionUri.ToString(), cancelTask.Token).ConfigureAwait(false);
                
                string resultJson;
                using (StreamReader reader = new StreamReader(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), Encoding.UTF8))
                {
                    try
                    {
                        resultJson = await reader.ReadToEndAsync().ConfigureAwait(false);

                        if (!string.IsNullOrEmpty(resultJson))
                        {
                            var entries = JsonConvert.DeserializeObject<RecentUploadedVideosQueryResult>(resultJson);

                            taskCompletitionSource.SetResult(entries);
                            resultJson = null;
                            entries = null;
                            response.Dispose();
                        }
                        else
                        {
                            response.Dispose();
                            taskCompletitionSource.SetResult(null);
                        }
                    }
                    catch (Exception ex)
                    {
                         response.Dispose();
                        taskCompletitionSource.SetException(ex);
                    }
                }
                 response.Dispose();
            }

            return await taskCompletitionSource.Task;
        }

        public async Task<IEnumerable<Models.Subscription.SubscriptionResult>> GetRecentUploadedVideosAsync(string userId, CancellationTokenSource cancelTask, string maxResults = "25", string startIndex = "1")
        {
            //https://gdata.youtube.com/feeds/api/users/qxxflu92fFt2eaCljH3Jmw/newsubscriptionvideos?v=2&start-index=1&max-results=5&alt=json
            StringBuilder petitionUri = new StringBuilder("https://gdata.youtube.com/feeds/api/users/");

            petitionUri.AppendFormat("{0}", userId);
            petitionUri.AppendFormat("/newsubscriptionvideos?v={0}", 2);
            petitionUri.AppendFormat("&max-results={0}", maxResults);
            petitionUri.AppendFormat("&start-index={0}", startIndex);
            petitionUri.Append("&alt=json");

            var taskCompletitionSource = new TaskCompletionSource<Entities.RecentUploadedVideosQueryResult.RecentUploadedVideosQueryResult>();
            var result = await ResolveRequest(petitionUri, taskCompletitionSource, cancelTask).ConfigureAwait(false);
            List<Models.Subscription.SubscriptionResult> list = new List<Models.Subscription.SubscriptionResult>();
            if (result == null)
                return null;
            if (result.Feed == null)
                return null;

            int count = 0;
                   
            string channelIds = string.Empty;
            string videoIds = string.Empty;
            channelProvider = new YoutubeChannelProvider();
            if (result.Feed.Entry == null)
                return list;
            for (int i = 0; i <= result.Feed.Entry.Count - 1; i++)
            {
                count++;
                var item = result.Feed.Entry.ElementAt(i);
                if (item.Id != null)
                {
                    if (count >= result.Feed.Entry.Count())
                    {
                        videoIds += item.MediaGroup.YtVideoid.T;
                        channelIds += item.MediaGroup.YtUploaderId.T;
                    }
                    else
                    {
                        videoIds += item.MediaGroup.YtVideoid.T + ",";
                        channelIds += item.MediaGroup.YtUploaderId.T + ",";
                    }
                }
            }

            var channelDataList = await channelProvider.SearchChannelByIdAsync(channelIds, cancelTask);
            
            foreach (var item in result.Feed.Entry)
            {
                try
                {
                    var data = new Models.Subscription.SubscriptionResult();
                    data.NextPageToken = result.Feed.Entry.Count.ToString();
                    data.SubcriptionId = string.Empty;
                    Entities.ChannelsQuery.Item channel = null;
                    if (channelDataList != null)
                    {
                        channel = channelDataList.Items.Where(x => x.Id.Equals(item.MediaGroup.YtUploaderId.T)).FirstOrDefault();
                        if (channel != null)
                        {
                            data.ChannelInfo = channel;
                        }
                    }

                    data.VideInfo = new Models.SearchVideo.Item();
                    data.VideInfo.snippet = new Models.SearchVideo.Snippet();
                    data.VideInfo.snippet.channelDetails = new ChannelSnippet();
                    data.VideInfo.snippet.channelDetails.Thumbnails = new Models.SearchVideo.Thumbnails();
                    data.VideInfo.snippet.contentDetails = new Models.SearchVideo.ContentDetails();
                    data.VideInfo.snippet.thumbnails = new Models.SearchVideo.Thumbnails();
                    data.VideInfo.snippet.statistics = new Onetube.Models.SearchVideo.Statistics();
                    data.VideInfo.id = new Models.SearchVideo.Id();
                    data.VideInfo.snippet.channelDetails.Description = item.MediaGroup.MediaDescription.T;
                    data.VideInfo.snippet.channelDetails.PublishedAt = item.Published.T;
                    data.VideInfo.snippet.channelDetails.Thumbnails.@default = new Models.SearchVideo.Default { url = item.MediaGroup.MediaThumbnail.FirstOrDefault(x => x.YtName.Contains("hq") || x.YtName.Contains("mq")).Url };
                    data.VideInfo.snippet.channelDetails.Title = item.Author.FirstOrDefault().Name.T;
                    data.VideInfo.snippet.channelId = item.MediaGroup.YtUploaderId.T;
                    data.VideInfo.snippet.channelTitle = item.Author.FirstOrDefault().Name.T;
                    data.VideInfo.snippet.contentDetails.duration = item.MediaGroup.YtDuration.Seconds;
                    data.VideInfo.snippet.description = item.MediaGroup.MediaDescription.T;
                    data.VideInfo.snippet.publishedAt = item.Published.T;
                    data.VideInfo.snippet.statistics = new Onetube.Models.SearchVideo.Statistics();
                    if (item.YtStatistics != null)
                    {
                        data.VideInfo.snippet.statistics.viewCount = item.YtStatistics.ViewCount;
                    }
                    else
                    {
                        data.VideInfo.snippet.statistics.viewCount = "0";
                    }
                    if (item.YtRating != null)
                    {
                        data.VideInfo.snippet.statistics.likeCount = item.YtRating.NumLikes;
                        data.VideInfo.snippet.statistics.dislikeCount = item.YtRating.NumDislikes;
                    }
                    else
                    {
                        data.VideInfo.snippet.statistics.likeCount = "0";
                        data.VideInfo.snippet.statistics.dislikeCount = "0";
                    }
                    data.VideInfo.snippet.thumbnails.medium = new Models.SearchVideo.Medium { url = item.MediaGroup.MediaThumbnail.FirstOrDefault(x => x.YtName.Contains("hq") || x.YtName.Contains("mq")).Url };
                    data.VideInfo.snippet.title = item.MediaGroup.MediaTitle.T;
                    data.VideInfo.id.videoId = item.MediaGroup.YtVideoid.T;
                    list.Add(data);
                }
                catch (Exception)
                {
                }
            }
            result = null;
            channelIds = null;
            channelProvider = null;
            petitionUri = null;
            channelDataList = null;
            return list;
        }

        public async Task<IEnumerable<Models.Activity>> GetActivitiesAsync(string userId, string startIndex, string maxResults)
        {
            // this.Request = string.Format("{0}users/{1}/events?alt=json&inline=true&start-index={2}&max-results={3}", (object)"https://gdata.youtube.com/feeds/api/", (object)this.userId, (object)(this.Offset + 1), (object)MainViewModel.Instance.MaxResult);
            StringBuilder petitionUri = new StringBuilder("https://gdata.youtube.com/feeds/api/");

            petitionUri.AppendFormat("users/{0}/events?v=2&alt=json&inline=true", userId);

            petitionUri.AppendFormat("&start-index={0}", startIndex);
            petitionUri.AppendFormat("&max-results={0}", maxResults);
            petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);
     
            HttpClient client = new HttpClient();
            
            var response = await client.GetAsync(petitionUri.ToString()).ConfigureAwait(false);
            var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            response.Dispose();
            client.Dispose();
            petitionUri = null;
            return await ParseActivities(result);
        }

        public async Task<IEnumerable<Activity>> GetActivitiesNextAsync(string userId, string startIndex, string maxResults)
        {
            StringBuilder petitionUri = new StringBuilder("https://gdata.youtube.com/feeds/api/");

            petitionUri.AppendFormat("users/{0}/events?v=2&alt=json&inline=true", userId);

            petitionUri.AppendFormat("&start-index={0}", startIndex);
            petitionUri.AppendFormat("&max-results={0}", maxResults);
            petitionUri.AppendFormat("&key={0}", AppKeys.API_KEY);

            HttpClient client = new HttpClient();

            var response = await client.GetAsync(petitionUri.ToString()).ConfigureAwait(false);
            var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            client.Dispose();
            response.Dispose();
            return await ParseActivities(result);
        }

        public async Task<List<Activity>> ParseActivities(string data)
        {
            JObject jobject;
            List<Activity> activities = new List<Activity>();
            try
            {
                jobject = JObject.Parse(data);
            }
            catch (Exception ex)
            {
                //  this.Error = ExceptionHandler.HandleError(data, ex);
                return null;
            }
            JToken jtoken1 = jobject["feed"];
            if (jtoken1 == null)
                return null;
            
            List<string> list = new List<string>();
            this.AvailableRecordCount = ExtentionMethods.JsonValueToInt(jtoken1[(object)"openSearch$totalResults"][(object)"$t"]);
            int activityCount = 0;
            if (this.AvailableRecordCount > 0)
            {
                JToken jtoken2 = jtoken1[(object)"entry"];
                if (jtoken2 != null)
                {
                    activityCount = Enumerable.Count<JToken>((IEnumerable<JToken>)jtoken2);
                    this.groupedCount = 0;
                    foreach (JToken jtoken3 in (IEnumerable<JToken>)jtoken2)
                    {
                        Activity activity = new Activity();
                        activity.Published = ExtentionMethods.JsonValueToDateTime(jtoken3[(object)"updated"][(object)"$t"]);
                        //  activity.PublishedDetailed = VideoCollection.GetPublishedDetailedValue(activity.Published);
                        JToken jtoken4 = Enumerable.FirstOrDefault<JToken>((IEnumerable<JToken>)jtoken3[(object)"category"], (Func<JToken, bool>)(n => ExtentionMethods.JsonValueToString(n[(object)"scheme"]) == "http://gdata.youtube.com/schemas/2007/userevents.cat"));
                        if (jtoken4 != null)
                        {
                            switch (ExtentionMethods.JsonValueToString(jtoken4[(object)"term"]))
                            {
                                case "video_added_to_playlist":
                                    activity.ActivityType = ActivityFeedType.Playlist;
                                    // activity.Image = new IsolatedImage((string)null, MainViewModel.Instance.Placeholders["PreviewVideoSmall"], ImageSize.Thumbnail, false, false, false);
                                    activity.ActivityName = ActivityNames.AddedVideoToPlaylist;
                                    break;
                                case "video_rated":
                                    activity.ActivityType = ActivityFeedType.Video;
                                    //  activity.Image = new IsolatedImage((string)null, MainViewModel.Instance.Placeholders["PreviewVideoSmall"], ImageSize.Thumbnail, false, false, false);
                                    activity.ActivityName = ActivityNames.Rated;
                                    break;
                                case "video_shared":
                                    activity.ActivityType = ActivityFeedType.Video;
                                    // activity.Image = new IsolatedImage((string)null, MainViewModel.Instance.Placeholders["PreviewVideoSmall"], ImageSize.Thumbnail, false, false, false);
                                    activity.ActivityName = ActivityNames.Shared;
                                    break;
                                case "video_favorited":
                                    activity.ActivityType = ActivityFeedType.Video;
                                    // activity.Image = new IsolatedImage((string)null, MainViewModel.Instance.Placeholders["PreviewVideoSmall"], ImageSize.Thumbnail, false, false, false);
                                    activity.ActivityName = ActivityNames.Favorited;
                                    break;
                                case "video_commented":
                                    activity.ActivityType = ActivityFeedType.Video;
                                    // activity.Image = new IsolatedImage((string)null, MainViewModel.Instance.Placeholders["PreviewVideoSmall"], ImageSize.Thumbnail, false, false, false);
                                    activity.ActivityName = ActivityNames.Commented;
                                    break;
                                case "video_uploaded":
                                    activity.ActivityType = ActivityFeedType.Video;
                                    // activity.Image = new IsolatedImage((string)null, MainViewModel.Instance.Placeholders["PreviewVideoSmall"], ImageSize.Thumbnail, false, false, false);
                                    activity.ActivityName = ActivityNames.Uploaded;
                                    break;
                                case "user_subscription_added":
                                    activity.ActivityType = ActivityFeedType.Channel;
                                    // activity.Image = new IsolatedImage((string)null, MainViewModel.Instance.Placeholders["PreviewChannelSmall"], true, false);
                                    activity.ActivityName = ActivityNames.Subscribed;
                                    break;
                                default:
                                    ++this.groupedCount;
                                    continue;
                            }
                            JToken jtoken5 = jtoken3[(object)"yt$groupId"];
                            if (jtoken5 != null)
                            {
                                activity.GroupId = ExtentionMethods.JsonValueToString(jtoken5[(object)"$t"]);
                                list.Add(activity.GroupId);
                                Activity activity1 = Enumerable.FirstOrDefault<Activity>((IEnumerable<Activity>)activities, (Func<Activity, bool>)(n => n.GroupId == activity.GroupId));
                                if (activity1 != null)
                                {
                                    if (activity.ActivityType == ActivityFeedType.Playlist && activity1.ActivityType == ActivityFeedType.Playlist)
                                    {
                                        int num = Enumerable.Count<string>((IEnumerable<string>)list, (Func<string, bool>)(n => n == activity.GroupId));
                                        if (num > 1)
                                            activity1.ActivityName = string.Format(ActivityNames.AddedVideoToPlaylist, (object)num);
                                    }
                                    else if (!string.IsNullOrEmpty(activity.ActivityName) && !new Regex(activity.ActivityName).IsMatch(activity1.ActivityName))
                                        activity1.ActivityName = string.Format("{0} {1} {2}", (object)activity1.ActivityName, (object)"&&", (object)activity.ActivityName);
                                    ++this.groupedCount;
                                    continue;
                                }
                            }
                        }
                        JToken jtoken6 = Enumerable.FirstOrDefault<JToken>((IEnumerable<JToken>)jtoken3[(object)"link"], (Func<JToken, bool>)(n => ExtentionMethods.JsonValueToString(n[(object)"rel"]) == "http://gdata.youtube.com/schemas/2007#video"));
                        if (jtoken6 != null)
                        {
                            JToken jtoken5 = Enumerable.FirstOrDefault<JToken>((IEnumerable<JToken>)jtoken6[(object)"entry"]);
                            if (jtoken5 != null)
                            {
                                activity.Id = ExtentionMethods.JsonValueToString(jtoken5[(object)"id"][(object)"$t"]);
                                activity.DisplayName = ExtentionMethods.JsonValueToString(jtoken5[(object)"title"][(object)"$t"]);
                                JToken jtoken7 = jtoken5[(object)"media$group"];
                                if (jtoken7 != null)
                                {
                                    if (jtoken7[(object)"media$thumbnail"] != null)
                                    {
                                        JToken jtoken8 = Enumerable.FirstOrDefault<JToken>((IEnumerable<JToken>)jtoken7[(object)"media$thumbnail"], (Func<JToken, bool>)(n => ExtentionMethods.JsonValueToString(n[(object)"yt$name"]) == "default"));
                                        if (jtoken8 != null)
                                        {
                                            activity.ThumbnailUrl = ExtentionMethods.JsonValueToString(jtoken8[(object)"url"]);
                                            //  activity.Image.LoadUrl(activity.ThumbnailUrl, ImageSize.Thumbnail, false, false);
                                        }
                                    }
                                    JToken jtoken9 = jtoken7[(object)"yt$duration"];
                                    if (jtoken9 != null)
                                        activity.Duration = ExtentionMethods.JsonValueToInt(jtoken9[(object)"seconds"]);
                                }
                            }
                        }
                        else
                        {
                            activity.DisplayName = string.Empty;
                            JToken jtoken5 = jtoken3[(object)"yt$userId"];
                            if (jtoken5 != null)
                                activity.Id = ExtentionMethods.JsonValueToString(jtoken5[(object)"$t"]);
                        }
                        activities.Add(activity);
                    }
                    jtoken1 = null;
                    jtoken2 = null;
                }
            }
            jobject = null;
            return await LoadBatchChannelDetails(activities);
        }

        public int AvailableRecordCount { get; set; }

        public int groupedCount { get; set; }

        public async Task<List<Activity>> LoadBatchChannelDetails(List<Activity> activities, bool canSupressFailedMessages = false)
        {
            if (activities == null)
                return null;

            var channelActivities = activities.Where(x => x.ActivityType == ActivityFeedType.Channel).ToList();
            
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("<feed xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:batch='http://schemas.google.com/gdata/batch' xmlns:yt='http://gdata.youtube.com/schemas/2007'>");
            stringBuilder.Append("<batch:operation type='query'/>");
            foreach (Activity activity in channelActivities)
                stringBuilder.AppendFormat("<entry><id>http://gdata.youtube.com/feeds/api/users/{0}</id></entry>", new object[1]
                {
                    (object)activity.Id
                });
            stringBuilder.Append("</feed>");

            HttpClient client = new HttpClient();
            var requestUri = "https://gdata.youtube.com/feeds/api/users/batch";
            var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
           
            request.Content = new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes(stringBuilder.ToString())));
            request.Content.Headers.Add("Content-Type", "application/atom+Xml");

            HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
            var data = await response.Content.ReadAsStringAsync();
            client.Dispose();
            request.Dispose();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                XNamespace xnamespace1 = (XNamespace)"http://www.w3.org/2005/Atom";
                XNamespace batchns = (XNamespace)"http://schemas.google.com/gdata/batch";
                XNamespace xnamespace2 = (XNamespace)"http://search.yahoo.com/mrss/";
                XNamespace ytns = (XNamespace)"http://gdata.youtube.com/schemas/2007";
                IEnumerable<XElement> source = XDocument.Parse(data).Descendants(xnamespace1 + "entry");
                foreach (XElement xelement in Enumerable.Where<XElement>(source, (Func<XElement, bool>)(n => n.Element(batchns + "status").Attribute((XName)"code").Value == "200")))
                {
                    XElement item = xelement;
                    //<atom:id>http://gdata.youtube.com/feeds/api/users/ZijND2e2tPp2AQL8Go2YSg</atom:id>
                    var idUri = item.Element(xnamespace1 + "id").Value;
                    if (!string.IsNullOrEmpty(idUri)) 
                    {
                        var elements = idUri.Split('/');
                        var id = elements.Last();
                        Activity activity = activities.FirstOrDefault(x => x.Id == id);
                        if (activity != null)
                        {
                            activity.DisplayName = item.Element(xnamespace1 + "title").Value;
                            activity.ThumbnailUrl = item.Element(xnamespace2 + "thumbnail").Attribute((XName)"url").Value;
                            // activity.Image.LoadUrl(activity.ThumbnailUrl, ImageSize.Thumbnail, false, false);
                            // activity.RaisePropertyChanged("DisplayName");
                        }
                    }
                }
                data = null;
                source = null;
                response.Dispose();
            }
            else
            {
                return null;
            }

            return activities;
        }
    }
}